#![feature(test)]
extern crate test;
use image::{imageops, DynamicImage, ImageFormat, ImageOutputFormat, Pixel, Rgba};
use nvjpeg::{CudaHostMemory, Decoder, PixelFormat};
use test::{black_box, Bencher};

macro_rules! decode {
    ($b:expr, $w:expr, $h:expr) => {
        let mut img = DynamicImage::new_rgba8($w, $h);
        let start = Rgba::from_slice(&[0, 128, 0, 0]);
        let end = Rgba::from_slice(&[255, 255, 255, 255]);
        imageops::vertical_gradient(&mut img, start, end);
        let mut bytes: Vec<u8> = Vec::new();
        img.write_to(&mut bytes, ImageOutputFormat::Jpeg(80))
            .unwrap();
        let decoder = Decoder::new().unwrap();
        $b.iter(|| {
            let image = decoder
                .decode(&bytes[..], PixelFormat::RgbInterleaved)
                .unwrap();
            assert_eq!(image.dimensions(), ($w, $h));
        });
    };
}

#[bench]
fn bench_decode_64x64(b: &mut Bencher) {
    decode!(b, 64, 64);
}

#[bench]
fn bench_decode_320x240(b: &mut Bencher) {
    decode!(b, 640, 480);
}

#[bench]
fn bench_decode_640x480(b: &mut Bencher) {
    decode!(b, 640, 480);
}

#[bench]
fn bench_decode_1280x720(b: &mut Bencher) {
    decode!(b, 1280, 720);
}

#[bench]
fn bench_decode_1920x1080(b: &mut Bencher) {
    decode!(b, 1920, 1080);
}

#[bench]
fn bench_get_image_info(b: &mut Bencher) {
    let mut img = DynamicImage::new_rgba8(1920, 1080);
    let start = Rgba::from_slice(&[0, 128, 0, 0]);
    let end = Rgba::from_slice(&[255, 255, 255, 255]);
    imageops::vertical_gradient(&mut img, start, end);
    let mut bytes: Vec<u8> = Vec::new();
    img.write_to(&mut bytes, ImageOutputFormat::Jpeg(80))
        .unwrap();
    let decoder = Decoder::new().unwrap();
    b.iter(|| {
        let info = decoder.get_image_info(&bytes[..]).unwrap();
        assert_eq!(info.widths[0], 1920);
        assert_eq!(info.heights[0], 1080);
        black_box(info);
    });
}
